package controller

import (
	"a-common/config"
	"a-common/constant"
	"a-common/myerr"
	"a-common/utils"
	"a-system/domain/pojo"
	"a-system/service"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sync"

	"github.com/gofiber/fiber/v2"
	"github.com/mssola/user_agent"
)

var (
	sysLoginControllerTemp *SysLoginController
	// cryptUtils             = utils.NewCryptUtils()
	captchaUtils           = utils.NewCaptchaUtils()
	emailUtils             = utils.NewEmailUtils()
	sysLoginService        = service.NewSysLoginService()
	sysLoginControllerOnce sync.Once
)

type SysLoginController struct{}

func NewSysLoginController() *SysLoginController {
	sysLoginControllerOnce.Do(func() {
		sysLoginControllerTemp = &SysLoginController{}
	})
	return sysLoginControllerTemp
}

// 简介主页
func (m *SysLoginController) GetIndex(c *fiber.Ctx) error {
	jsonStr := `{
        "site": {
            "siteName": "BuildAdmin",
            "recordNumber": "渝ICP备8888888号-1",
            "version": "v1.0.0",
            "cdnUrl": "\/\/127.0.0.1:8000",
            "upload": {
                "maxSize": 10485760,
                "saveName": "\/storage\/{topic}\/{year}{mon}{day}\/{fileName}{fileSha1}{.suffix}",
                "allowedSuffixes": "jpg,png,bmp,jpeg,gif,webp,zip,rar,wav,mp4,mp3",
                "allowedMimeTypes": [],
                "mode": "local"
            }
        },
        "openMemberCenter": true,
        "userInfo": [],
        "rules": [],
        "menus": []
    }`
	var jsonObj map[string]json.RawMessage
	// 解码JSON字符串到map
	if err := json.Unmarshal([]byte(jsonStr), &jsonObj); err != nil {
		return err
	}
	return Resp(c, jsonObj)
}

// GetImg 获取图片
func (m *SysLoginController) GetImg(c *fiber.Ctx) error {
	// 获取下载文件的路径
	filename := c.Params("filename")

	stRootDir, _ := os.Getwd()
	filepath := filepath.Join(stRootDir, "resources", "static", "images", filename)

	// 读取文件内容
	file, err := os.ReadFile(filepath)
	if err != nil {
		return err
	}

	// 设置响应头，告诉浏览器这是一个可下载的文件
	c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
	return c.Send(file)
}

// Login 用户登陆
func (m *SysLoginController) Login(c *fiber.Ctx) error {
	var ip string
	var userName string
	var err error
	defer func() {
		// 获取 User-Agent
		userAgentString := c.Get("User-Agent", "")
		ua := user_agent.New(userAgentString)
		// 获取操作系统信息
		osInfo := ua.OSInfo()
		// 获取浏览器信息
		bName, bVersion := ua.Browser()
		sysLogininforService.Add(ip, userName, constant.PC, bName, bVersion, osInfo.Name, osInfo.Version, err)
	}()

	var args pojo.SysLoginDto
	if err := c.BodyParser(&args); err != nil {
		return myerr.ERR_SYS_ARGS
	}
	err = args.Validator()
	if err != nil {
		return myerr.ERR_LOGIN_ARGS
	}
	userName = args.Username

	// 获取客户端真实 IP 地址
	ip = utils.NewIpUtils().GetIP(c)

	userId, username, nickname, avatar, t, token, refToken, err := sysLoginService.Login(&args, ip)
	if err != nil {
		return err
	}
	return Resp(c, fiber.Map{
		"userInfo": fiber.Map{
			"id":              userId,
			"username":        username,
			"nickname":        nickname,
			"avatar":          avatar,
			"last_login_time": t,
			"token":           token,
			"refresh_token":   refToken,
		},
	})
}

// RefreshToken 刷新token
func (m *SysLoginController) RefreshToken(c *fiber.Ctx) error {
	refToken := c.Params("refToken")

	// 校验token合法性
	ip := utils.NewIpUtils().GetIP(c)
	jwtClaims, err := utils.ParseToken(refToken, ip)
	if err != nil || jwtClaims.ID == 0 {
		return myerr.ERR_LOGIN_AUTH
	}
	token, err := sysLoginService.RefreshToken(refToken)
	if err != nil {
		return err
	}
	return Resp(c, token)
}

// GetInfo 获取登陆信息
func (m *SysLoginController) GetInfo(c *fiber.Ctx) error {
	user := GetUser(c)
	vUser, menus, err := sysLoginService.GetInfo(user.Uid)
	if err != nil {
		return err
	}

	siteConfig := `{
		"siteName": "BuildAdmin演示站",
		"version": "v1.0.0",
		"cdnUrl": "\/\/demo.buildadmin.com",
		"apiUrl": "https:\/\/buildadmin.com",
		"upload": {
			"maxsize": 10485760,
			"savename": "\/storage\/{topic}\/{year}{mon}{day}\/{filename}{filesha1}{.suffix}",
			"mimetype": "jpg,png,bmp,jpeg,gif,webp,zip,rar,xls,xlsx,doc,docx,wav,mp4,mp3,txt",
			"mode": "local"
		}
	}`

	terminal := `{
		"installServicePort": "8000",
		"npmPackageManager": "pnpm"
	}`

	return Resp(c, fiber.Map{
		"adminInfo":  vUser,
		"menus":      menus,
		"siteConfig": siteConfig,
		"terminal":   terminal,
	})
}

// GetDash 首页
func (m *SysLoginController) GetDash(c *fiber.Ctx) error {
	return Resp(c, fiber.Map{
		"remark": "开源等于互助；开源需要大家一起来支持，支持的方式有很多种，比如使用、推荐、写教程、保护生态、贡献代码、回答问题、分享经验、打赏赞助等；欢迎您加入我们！",
	})
}

func (m *SysLoginController) GetRouters(c *fiber.Ctx) error {
	user := GetUser(c)
	mp, err := sysLoginService.GetRouters(user.Uid)
	if err != nil {
		return err
	}
	return Resp(c, mp)
}

// LoginOut 退出登陆
func (m *SysLoginController) LoginOut(c *fiber.Ctx) error {
	user := GetUser(c)
	if user.Uid != 0 {
		err := sysLoginService.LoginOut(user.Account)
		if err != nil {
			return err
		}
	}
	return Ok(c)
}

// Register 注册用户
func (m *SysLoginController) Register(c *fiber.Ctx) error {
	return Ok(c)
}

// CaptchaImage 获取图片验证码
func (m *SysLoginController) CaptchaImage(c *fiber.Ctx) error {
	captchaEnabled := config.Config.Login.CaptchaEnable
	if !captchaEnabled {
		return Resp(c, fiber.Map{
			"captchaEnabled": captchaEnabled,
		})
	}
	id, b64s, _, err := sysLoginService.CaptchaImage()
	if err != nil {
		return err
	}
	return Resp(c, fiber.Map{
		"captchaEnabled": captchaEnabled,
		"uuid":           id,
		"img":            b64s,
	})
}

func (m *SysLoginController) CaptchaVerify(c *fiber.Ctx) error {
	id := c.Query("id")
	code := c.Query("code")
	ok := captchaUtils.CaptchaVerify(id, code)
	if !ok {
		return myerr.ERR_LOGIN_VERIFY
	}
	return Ok(c)
}

// GetEmailCode 获取邮箱验证码
func (m *SysLoginController) GetEmailCode(c *fiber.Ctx) error {
	email := c.Query("email")
	err := emailUtils.SendCode(email, "验证码", "获取验证码")
	if err != nil {
		return err
	}
	return Ok(c)
}

func (m *SysLoginController) EmailCodeVerify(c *fiber.Ctx) error {
	email := c.Query("email")
	code := c.Query("code")
	ok := emailUtils.Verify(email, code)
	if !ok {
		return myerr.ERR_LOGIN_VERIFY
	}
	return Ok(c)
}
